// routes/alert.go
package routes

import (
	"fmt"
	"log"
	"net/url"
	"time"

	"v2/alertconverter"
	"v2/config"
	"v2/dingtalk"
	"v2/feishu"
	"v2/model"
	"v2/utils"

	"v2/middleware"
	"v2/wecom"

	"github.com/gin-gonic/gin"

	_ "v2/docs" // 必须导入，否则 swag 扫到
)

// 初始化飞书 Stream 处理器
var feishuStreamHandler *feishu.FeishuStreamHandler

// 初始化钉钉 Stream 处理器
var dingTalkStreamHandler *dingtalk.DingTalkStreamHandler

// @title Odysseus_DiTing API
// @version 1.0
// @description 告警转发服务：支持企业微信、飞书、钉钉
// @host localhost:8080
// @BasePath /alert
// @schemes http
func SetupAlertRoutes(r *gin.Engine) {

	// ✅ 1. 先注册不需要鉴权的 GET 路由（用于验证）
	r.GET("/alert/wecom-app", HandleWeComAppVerify)         // 注意：这里直接挂在 r 上，不在 group 内
	r.GET("/alert/dingtalk-http", HandleDingTalkHTTPVerify) // 注意：这里直接挂在 r 上，不在 group 内

	group := r.Group("/alert")
	// group.Use(middleware.BasicAuthMiddleware(config.Global.BasicAuth.Username,
	// 	config.Global.BasicAuth.Password))
	group.POST("/wecom", HandleWeCom)
	group.POST("/feishu", HandleFeiShu)
	group.POST("/dingtalk", HandleDingTalk)
	group.POST("/wecom-app", HandleWeComApp) //这个是回调接口走的逻辑
	group.POST("/dingtalk-app", HandleDingTalkApp)
	group.POST("/feishu-app", HandleFeiShuApp)
	group.POST("/feishu-stream", middleware.RequestLogger(), HandleFeishuStreamAlert)
	group.GET("/feishu-stream/status", GetFeiShuStreamStatus)
	group.POST("/dingtalk-stream", HandleDingTalkStreamAlert)

	// 新增：不同告警源的路由
	group.POST("/skywalking", HandleSkyWalkingAlert)
	group.POST("/kube-event", HandleKubeEventAlert)
	group.POST("/falco", HandleFalcoAlert)

	// 企业微信应用交互式卡片回调处理
	// 新增：企业微信真实回调路由（参考钉钉Stream）
	group.GET("/wecom/callback", wecom.HandleWeComAppCallback)
	group.POST("/wecom-app/callback", wecom.HandleWeComAppCallback)

}

func SetFeishuStreamHandler(handler *feishu.FeishuStreamHandler) {
	feishuStreamHandler = handler
}

func SetDingTalkStreamHandler(handler *dingtalk.DingTalkStreamHandler) {
	dingTalkStreamHandler = handler
}

// 企业微信webhook
// HandleWeCom godoc
// @Summary 发送到企业微信
// @Description 将告警转发到企业微信机器人
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /wecom [post]
func HandleWeCom(c *gin.Context) {
	if !config.Global.Notifier.WeCom.Enable {
		c.JSON(403, gin.H{"error": "企业微信通知已禁用"})
		return
	}
	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}
	var alert model.AlertInfo
	alert.FromAlertData(data)
	if err := wecom.NewWeComNotifier(config.Global.Notifier.WeCom.Webhook).Send(alert); err != nil {
		log.Printf("❌ 发送企业微信失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}
	c.JSON(200, gin.H{"status": "ok", "sent_to": "wecom"})
}

// 飞书webhook机器人
// HandleFeiShu godoc
// @Summary 发送到飞书
// @Description 将告警转发到飞书机器人
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /feishu [post]
func HandleFeiShu(c *gin.Context) {
	if !config.Global.Notifier.FeiShu.Enable {
		c.JSON(403, gin.H{"error": "飞书通知已禁用"})
		return
	}
	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}
	var alert model.AlertInfo
	alert.FromAlertData(data)
	if err := feishu.NewFeiShuNotifier(config.Global.Notifier.FeiShu.Webhook).Send(alert); err != nil {
		log.Printf("❌ 发送飞书失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}
	c.JSON(200, gin.H{"status": "ok", "sent_to": "feishu"})
}

// 钉钉webhook机器人
// HandleDingTalk godoc
// @Summary 发送到钉钉
// @Description 将告警转发到钉钉机器人
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /dingtalk [post]
func HandleDingTalk(c *gin.Context) {
	if !config.Global.Notifier.DingTalk.Enable {
		c.JSON(403, gin.H{"error": "钉钉通知已禁用"})
		return
	}
	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}
	var alert model.AlertInfo
	alert.FromAlertData(data)
	if err := dingtalk.NewDingTalkRobotNotifier(config.Global.Notifier.DingTalk.Webhook).Send(alert); err != nil {
		log.Printf("❌ 发送钉钉失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}
	c.JSON(200, gin.H{"status": "ok", "sent_to": "dingtalk"})
}

// 企业微信机器人
// HandleWeComApp godoc
// @Summary 发送到企业微信应用
// @Description 将告警转发到企业微信应用消息
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} gin.H
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Router /wecom-app [post]
func HandleWeComApp(c *gin.Context) {
	if !config.Global.Notifier.WeComApp.Enable {
		c.JSON(403, gin.H{"error": "企业微信应用已禁用"})
		return
	}
	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}
	var alert model.AlertInfo
	alert.FromAlertData(data)
	if err := wecom.NewWeComAppNotifier(
		config.Global.Notifier.WeComApp.CorpID,
		config.Global.Notifier.WeComApp.Secret,
		int64(config.Global.Notifier.WeComApp.AgentID),                // 修复：确保AgentID为int64类型
		fmt.Sprintf("http://localhost:%d", config.Global.Server.Port), // 使用服务器配置构建BaseURL
	).Send(alert); err != nil {
		log.Printf("❌ 发送企业微信应用失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}
	c.JSON(200, gin.H{"status": "ok", "sent_to": "wecom-app"})
}

// HandleDingTalkApp godoc
// @Summary 发送到钉钉应用
// @Description 将告警转发到钉钉应用消息
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} gin.H
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Router /dingtalk-app [post]
func HandleDingTalkApp(c *gin.Context) {
	if !config.Global.Notifier.DingTalkApp.Enable {
		c.JSON(403, gin.H{"error": "钉钉应用已禁用"})
		return
	}

	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}

	var alert model.AlertInfo
	alert.FromAlertData(data)

	// ✅ 修复点：正确传递参数
	if err := dingtalk.NewDingTalkAppNotifier(
		config.Global.Notifier.DingTalkApp.AppKey,    // 第一个参数：AppKey
		config.Global.Notifier.DingTalkApp.AppSecret, // 第二个参数：AppSecret
		config.Global.Notifier.DingTalkApp.AgentID,   // 第三个参数：AgentID
	).Send(alert); err != nil {
		log.Printf("❌ 发送钉钉应用失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}

	c.JSON(200, gin.H{"status": "ok", "sent_to": "dingtalk-app"})
}

// 飞书应用
// HandleFeiShuApp godoc
// @Summary 发送到飞书应用
// @Description 将告警转发到飞书应用消息
// @Tags Alert
// @Accept json
// @Produce json
// @Param alert body model.AlertData true "告警数据"
// @Success 200 {object} gin.H
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Router /feishu-app [post]
func HandleFeiShuApp(c *gin.Context) {
	if !config.Global.Notifier.FeiShuApp.Enable {
		c.JSON(403, gin.H{"error": "飞书应用已禁用"})
		return
	}
	var data model.AlertData
	if err := c.ShouldBindJSON(&data); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}
	var alert model.AlertInfo
	alert.FromAlertData(data)

	// ✅ 传入 app_id, app_secret, receive_id_type
	if err := feishu.NewFeiShuAppNotifier(
		config.Global.Notifier.FeiShuApp.AppID,
		config.Global.Notifier.FeiShuApp.AppSecret,
		config.Global.Notifier.FeiShuApp.ReceiveIDType,
	).Send(alert); err != nil {
		log.Printf("❌ 发送飞书应用失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}
	c.JSON(200, gin.H{"status": "ok", "sent_to": "feishu-app"})
}

// routes/alert.go 企业微信应用消息验证
func HandleWeComAppVerify(c *gin.Context) {
	msgSignature := c.Query("msg_signature")
	timestamp := c.Query("timestamp")
	nonce := c.Query("nonce")
	echoStr := c.Query("echostr")

	// URL 解码
	decodedEchoStr, err := url.QueryUnescape(echoStr)
	if err != nil {
		decodedEchoStr = echoStr
	}

	crypto := utils.NewWecomCrypto(
		config.Global.Notifier.WeComApp.MsgEncToken,
		config.Global.Notifier.WeComApp.MsgEncEncodingAESKey,
		config.Global.Notifier.WeComApp.CorpID,
	)

	// ✅ 使用 decodedEchoStr 参与签名
	if !crypto.ValidateSignature(crypto.Token, timestamp, nonce, decodedEchoStr, msgSignature) {
		c.String(403, "Invalid signature")
		return
	}

	plaintext, err := crypto.DecryptEchoStr(decodedEchoStr)
	if err != nil {
		log.Printf("❌ 解密 echostr 失败: %v", err)
		c.String(400, "Decrypt failed")
		return
	}

	c.String(200, plaintext)
}

// HandleDingTalkHTTPVerify godoc
// @Summary 钉钉 HTTP 事件推送验证
// @Description 用于钉钉事件订阅验证
// @Tags Alert
// @Router /alert/dingtalk-http [get]
func HandleDingTalkHTTPVerify(c *gin.Context) {
	signature := c.Query("signature")
	timestamp := c.Query("timestamp")
	nonce := c.Query("nonce")
	echoStr := c.Query("echostr")

	crypto := utils.NewDingTalkCrypto(
		config.Global.Notifier.DingTalkHTTP.Token,
		config.Global.Notifier.DingTalkHTTP.EncodingAESKey,
		config.Global.Notifier.DingTalkHTTP.AppKey,
	)

	if !crypto.ValidateSignature(signature, timestamp, nonce, echoStr) {
		c.String(403, "Invalid signature")
		return
	}

	// 返回加密后的 echostr
	encrypted, err := crypto.EncryptResponse(echoStr)
	if err != nil {
		c.String(500, "Encrypt failed")
		return
	}

	c.String(200, encrypted)
}

// HandleFeishuStreamAlert 处理飞书 Stream 告警
// HandleFeishuStreamAlert 处理飞书 Stream 告警
func HandleFeishuStreamAlert(c *gin.Context) {
	var alertData model.AlertData
	if err := c.ShouldBindJSON(&alertData); err != nil {
		log.Printf("[FeiShu] 请求解析失败: %v", err)
		c.JSON(400, gin.H{
			"error":  "无效JSON",
			"detail": err.Error(),
		})
		return
	}

	log.Printf("[FeiShu] 收到告警数据: %+v", alertData)

	// 转换为 AlertInfo
	var alert model.AlertInfo
	alert.FromAlertData(alertData)

	// 确保有 ID
	if alert.ID == "" {
		alert.ID = fmt.Sprintf("%d", time.Now().Unix())
	}

	// 发送告警卡片
	if feishuStreamHandler == nil {
		log.Println("[FeiShu] Stream 处理器未初始化")
		c.JSON(500, gin.H{"error": "内部错误", "detail": "Stream 处理器未初始化"})
		return
	}

	if err := feishuStreamHandler.SendAlert(alert); err != nil {
		log.Printf("[FeiShu] 发送告警失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}

	c.JSON(200, gin.H{
		"status":   "ok",
		"message":  "告警已发送",
		"alert_id": alert.ID,
	})
}

// GetFeiShuStreamStatus 获取飞书 Stream 状态
func GetFeiShuStreamStatus(c *gin.Context) {
	isRunning := false
	if feishuStreamHandler != nil {
		isRunning = feishuStreamHandler.IsRunning()
	}

	log.Printf("[FeiShu] 返回 Stream 状态: isRunning=%v", isRunning)

	c.JSON(200, gin.H{
		"status":        "ok",
		"is_running":    isRunning,
		"config_loaded": feishuStreamHandler != nil,
	})
}

func HandleDingTalkStreamAlert(c *gin.Context) {
	var alertData model.AlertData
	if err := c.ShouldBindJSON(&alertData); err != nil {
		log.Printf("[dingtalkstream] 请求解析失败: %v", err)
		c.JSON(400, gin.H{
			"error":  "无效JSON",
			"detail": err.Error(),
		})
		return
	}

	log.Printf("[dingtalkstream] 收到告警数据: %+v", alertData)

	// 转换为 AlertInfo
	var alert model.AlertInfo
	alert.FromAlertData(alertData)

	// 确保有 ID
	if alert.ID == "" {
		alert.ID = fmt.Sprintf("%d", time.Now().Unix())
	}

	// 发送告警卡片
	if dingTalkStreamHandler == nil {
		log.Println("[DingTalk] Stream 处理器未初始化")
		c.JSON(500, gin.H{"error": "内部错误", "detail": "Stream 处理器未初始化"})
		return
	}

	if err := dingTalkStreamHandler.SendAlert(alert); err != nil {
		log.Printf("[DingTalk] 发送告警失败: %v", err)
		c.JSON(500, gin.H{"error": "发送失败", "detail": err.Error()})
		return
	}

	c.JSON(200, gin.H{
		"status":   "ok",
		"message":  "告警已发送",
		"alert_id": alert.ID,
	})
}

// HandleSkyWalkingAlert 处理 SkyWalking 告警
func HandleSkyWalkingAlert(c *gin.Context) {
	// 只处理文本格式的SkyWalking告警
	var textAlert alertconverter.SkyWalkingTextAlert
	if err := c.ShouldBindJSON(&textAlert); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}

	// 打印接收到的原始数据用于调试
	fmt.Printf("[SkyWalking] 接收到原始数据: %+v\n", textAlert)
	fmt.Printf("[SkyWalking] 告警内容: %s\n", textAlert.Text.Content)

	// 处理文本格式的SkyWalking告警
	handleTextSkyWalkingAlert(c, textAlert)
}

// handleTextSkyWalkingAlert 处理文本格式的SkyWalking告警
func handleTextSkyWalkingAlert(c *gin.Context, textAlert alertconverter.SkyWalkingTextAlert) {
	// 记录数据源信息
	dataSource := "skywalking-text"

	// 记录详细的处理信息
	receivedTime := time.Now()
	fmt.Printf("[%s] 📥 接收到 %s 告警\n",
		receivedTime.Format("2006-01-02 15:04:05"),
		dataSource)
	fmt.Printf("原始数据: %+v\n", textAlert)
	fmt.Printf("内容: %s\n", textAlert.Text.Content)

	// 转换为统一的告警格式
	alertData := alertconverter.ConvertSkyWalkingTextAlert(textAlert)
	fmt.Printf("转换后的AlertData: %+v\n", alertData)

	// 转换为 AlertInfo
	var alert model.AlertInfo
	alert.FromAlertData(alertData)
	fmt.Printf("转换后的AlertInfo: %+v\n", alert)

	// 发送到所有启用的通知渠道
	sendToAllChannels(alert)

	// 计算处理时间
	processingTime := time.Since(receivedTime)

	c.JSON(200, gin.H{
		"status":          "ok",
		"message":         fmt.Sprintf("%s 告警处理成功", dataSource),
		"data_source":     dataSource,
		"alert_content":   textAlert.Text.Content,
		"processing_time": fmt.Sprintf("%v", processingTime),
	})
}

// HandleKubeEventAlert 处理 Kubernetes 事件告警
func HandleKubeEventAlert(c *gin.Context) {
	var kubeEventAlert alertconverter.KubeEventAlert
	if err := c.ShouldBindJSON(&kubeEventAlert); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}

	// 记录数据源信息
	dataSource := "kube-event"
	// 如果有显式的数据源标识，使用它
	if kubeEventAlert.Type == "data_source" {
		dataSource = kubeEventAlert.Reason
	}

	// 记录详细的处理信息
	receivedTime := time.Now()
	fmt.Printf("[%s] 📥 接收到 %s 事件: %s (Reason: %s, Namespace: %s)\n",
		receivedTime.Format("2006-01-02 15:04:05"),
		dataSource,
		kubeEventAlert.Name,
		kubeEventAlert.Reason,
		kubeEventAlert.Namespace)

	// 转换为统一的告警格式
	alertData := alertconverter.ConvertKubeEventAlert(kubeEventAlert)

	// 转换为 AlertInfo
	var alert model.AlertInfo
	alert.FromAlertData(alertData)

	// 检查是否是 kube-event 类型，如果是则生成专门的卡片消息
	if alertData.Cate == "kube-event" {
		// 生成专门的卡片消息
		cardMessage := alertconverter.GenerateKubeEventCardMessage(alertData)

		// 将卡片消息添加到 alert.TagsMap 中，以便所有通知渠道都能使用
		if alert.TagsMap == nil {
			alert.TagsMap = make(map[string]string)
		}
		alert.TagsMap["card_message"] = cardMessage
	}

	// 发送到所有启用的通知渠道
	sendToAllChannels(alert)

	// 计算处理时间
	processingTime := time.Since(receivedTime)

	c.JSON(200, gin.H{
		"status":          "ok",
		"message":         fmt.Sprintf("%s 事件处理成功", dataSource),
		"data_source":     dataSource,
		"event_name":      kubeEventAlert.Name,
		"event_reason":    kubeEventAlert.Reason,
		"event_namespace": kubeEventAlert.Namespace,
		"processing_time": fmt.Sprintf("%v", processingTime),
	})
}

// HandleFalcoAlert 处理 Falco 告警
func HandleFalcoAlert(c *gin.Context) {
	var falcoAlert alertconverter.FalcoAlert
	if err := c.ShouldBindJSON(&falcoAlert); err != nil {
		c.JSON(400, gin.H{"error": "无效JSON", "detail": err.Error()})
		return
	}

	// 记录数据源信息
	dataSource := "falco"
	// 如果有显式的数据源标识，使用它
	if falcoAlert.OutputFields != nil {
		if ds, ok := falcoAlert.OutputFields["data_source"].(string); ok && ds != "" {
			dataSource = ds
		}
	}

	// 记录详细的处理信息
	receivedTime := time.Now()
	fmt.Printf("[%s] 📥 接收到 %s 告警: %s (Rule: %s)\n",
		receivedTime.Format("2006-01-02 15:04:05"),
		dataSource,
		falcoAlert.Output,
		falcoAlert.Rule)

	// 转换为统一的告警格式
	alertData := alertconverter.ConvertFalcoAlert(falcoAlert)

	// 转换为 AlertInfo
	var alert model.AlertInfo
	alert.FromAlertData(alertData)

	// 检查是否是 falco 类型，如果是则生成专门的卡片消息
	if alertData.Cate == "falco" {
		// 生成专门的卡片消息
		cardMessage := alertconverter.GenerateFalcoCardMessage(alertData)

		// 将卡片消息添加到 alert.TagsMap 中，以便所有通知渠道都能使用
		if alert.TagsMap == nil {
			alert.TagsMap = make(map[string]string)
		}
		alert.TagsMap["card_message"] = cardMessage
	}

	// 发送到所有启用的通知渠道
	sendToAllChannels(alert)

	// 计算处理时间
	processingTime := time.Since(receivedTime)

	c.JSON(200, gin.H{
		"status":          "ok",
		"message":         fmt.Sprintf("%s 告警处理成功", dataSource),
		"data_source":     dataSource,
		"alert_rule":      falcoAlert.Rule,
		"alert_output":    falcoAlert.Output,
		"processing_time": fmt.Sprintf("%v", processingTime),
	})
}

// sendToAllChannels 发送到所有启用的通知渠道
func sendToAllChannels(alert model.AlertInfo) {
	// 发送到企业微信
	if config.Global.Notifier.WeCom.Enable {
		wecom.NewWeComNotifier(config.Global.Notifier.WeCom.Webhook).Send(alert)
	}

	// 发送到飞书
	if config.Global.Notifier.FeiShu.Enable {
		feishu.NewFeiShuNotifier(config.Global.Notifier.FeiShu.Webhook).Send(alert)
	}

	// 发送到钉钉
	if config.Global.Notifier.DingTalk.Enable {
		dingtalk.NewDingTalkRobotNotifier(config.Global.Notifier.DingTalk.Webhook).Send(alert)
	}

	// 发送到企业微信应用
	if config.Global.Notifier.WeComApp.Enable {
		wecom.NewWeComAppNotifier(
			config.Global.Notifier.WeComApp.CorpID,
			config.Global.Notifier.WeComApp.Secret,
			int64(config.Global.Notifier.WeComApp.AgentID),
			fmt.Sprintf("http://localhost:%d", config.Global.Server.Port),
		).Send(alert)
	}

	// 发送到钉钉应用
	if config.Global.Notifier.DingTalkApp.Enable {
		dingtalk.NewDingTalkAppNotifier(
			config.Global.Notifier.DingTalkApp.AppKey,
			config.Global.Notifier.DingTalkApp.AppSecret,
			config.Global.Notifier.DingTalkApp.AgentID,
		).Send(alert)
	}

	// 发送到飞书应用
	if config.Global.Notifier.FeiShuApp.Enable {
		feishu.NewFeiShuAppNotifier(
			config.Global.Notifier.FeiShuApp.AppID,
			config.Global.Notifier.FeiShuApp.AppSecret,
			config.Global.Notifier.FeiShuApp.ReceiveIDType,
		).Send(alert)
	}
}
